﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ConnectionMeta.cs" company="Data Ductus Malmö">
//   (c) 2010 - 2012 Data Ductus Malmö AB
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace DataDuctus.Snmp.Persistor.Core.MetaData
{
  using System;

  using Lextm.SharpSnmpLib;

  /// <summary>
  /// The connection meta.
  /// </summary>
  public class ConnectionMeta
  {
    #region Public Properties

    /// <summary>
    /// Gets or sets what type of connection the properties describes.
    /// </summary>
    public ConnectionType ConnectionType { get; set; }

    /// <summary>
    /// Gets or sets the IP of the SNMP Entity.
    /// </summary>
    public string Host { get; set; }

    /// <summary>
    /// Gets or sets the port to use.
    /// </summary>
    public int Port { get; set; }

    /// <summary>
    /// Gets or sets the security string used for connections.
    /// </summary>
    public string SecurityString { get; set; }

    /// <summary>
    /// Gets or sets the timeout while doing requests.
    /// </summary>
    public int Timeout { get; set; }

    /// <summary>
    /// Gets or sets the version of the SNMP to use.
    /// </summary>
    public VersionCode Version { get; set; }

    #endregion

    #region Public Methods and Operators

    /// <summary>
    /// Creates a instance of <see cref="ConnectionMeta"/> based on a snmp url.
    /// </summary>
    /// <param name="url">
    /// The snmp url.
    /// </param>
    /// <returns>
    /// A valid instance of <see cref="ConnectionMeta"/>.
    /// </returns>
    /// <remarks>
    /// The snmp url in on the following format: 
    /// 'snmp://1.2.3.4:161/v2c/read/public'. There are three different connection
    /// types: read, write, notify.
    /// </remarks>
    public static ConnectionMeta FromUrl(string url)
    {
      string[] data = url.Split('/');

      string host = data[2];
      VersionCode version = VersionCodeFromString(data[3]);
      string securityString = data[5];

      ConnectionType connectionType = FromString(data[4]);

      int port;
      int idx = host.IndexOf(':');

      if (-1 == idx)
      {
        port = 161;
      }
      else
      {
        port = int.Parse(host.Substring(idx + 1));
        host = host.Substring(0, idx);
      }

      return new ConnectionMeta
        {
          Host = host, 
          Port = port, 
          Version = version, 
          SecurityString = securityString, 
          ConnectionType = connectionType
        };
    }

    #endregion

    #region Methods

    /// <summary>
    /// The from string.
    /// </summary>
    /// <param name="connectionType">
    /// The connection type.
    /// </param>
    /// <returns>
    /// A <see cref="ConnectionType"/>.
    /// </returns>
    /// <exception cref="ArgumentException">If incorrect value in <paramref name="connectionType"/>.</exception>
    private static ConnectionType FromString(string connectionType)
    {
      switch (connectionType)
      {
        case "read":
          return ConnectionType.Read;

        case "write":
          return ConnectionType.Write;

        case "notify":
          return ConnectionType.Notify;
      }

      throw new ArgumentException(
        string.Format("Cannot handle connection type = {0} only read, write or notify is available.", connectionType), 
        "connectionType");
    }

    /// <summary>
    /// The version code from string.
    /// </summary>
    /// <param name="version">
    /// The version.
    /// </param>
    /// <returns>
    /// <see cref="VersionCode"/>.
    /// </returns>
    /// <exception cref="ArgumentException">If incorrect version in <paramref name="version"/> parameter.</exception>
    private static VersionCode VersionCodeFromString(string version)
    {
      switch (version)
      {
        case "v1":
          return VersionCode.V1;

        case "v2c":
          return VersionCode.V2;

        case "v3":
          return VersionCode.V3;

        default:
          throw new ArgumentException(string.Format("Version = '{0}' not recognized", version), "version");
      }

      #endregion // Private Helpers
    }
  }
}